﻿//by  张海军 710605420@qq.com
using LazyFramework.UI;
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Entities;
using UnityEngine;
using UnityEngine.EventSystems;
using XLua;

namespace LazyFramework
{
    public class UGUIManager : MonoSingleton<UGUIManager>
    {
        private float m_TTF = 30;
        private Camera m_UICamera = null;
        private int m_UILayer = 0;

        private Dictionary<int, UIViewBase> m_allUIs = new Dictionary<int, UIViewBase>();
        private List<UIViewBase> m_OpenUIs = new List<UIViewBase>();
        private List<UIViewBase> m_ReleaseUI = new List<UIViewBase>();
        private Hashtable m_loadingUIs = new Hashtable();

        private void Awake()
        {
            m_UILayer = LayerMask.NameToLayer("UI"); 
            CreateEventSystem();
            m_UICamera = CreateUICamera();
#if HOTFIX_ENABLE
            //加载lua
            var xlua = XluaManager.Instance;
#endif
        }

        public void Initialize()
        {
            //加载配置
            UIConfig.Instance.Load();
        }
        private GameObject CreateEventSystem()
        {
            GameObject EventSystemGo = new GameObject("EventSystem");
            EventSystemGo.transform.SetParent(transform);
            EventSystem eventSystem = EventSystemGo.AddComponent<EventSystem>();
            StandaloneInputModule standaloneInputModule = EventSystemGo.AddComponent<StandaloneInputModule>();
            return EventSystemGo;
        }
        private Camera CreateUICamera()
        {
            GameObject cameraGo = new GameObject("uiCamera");
            cameraGo.transform.SetParent(transform);
            cameraGo.transform.SetSiblingIndex(0);
            Camera uiCamera = cameraGo.AddComponent<Camera>();
            uiCamera.cullingMask = 1<<LayerMask.NameToLayer("UI");
            uiCamera.orthographic = true;
            uiCamera.clearFlags = CameraClearFlags.SolidColor;
            return uiCamera;
        }
        private T CreateClass<T>(string type) where T:UIViewBase,new()
        {
            T tInstance = (T)World.Active.CreateSystem(Type.GetType(type, true));
            return tInstance;
        }
        private UIViewBase CreateUI(UIType uiType)
        {
            UIViewBase uiView = null;
            UIConfig.Info uiInfo = UIConfig.Instance.GetUIConfig(uiType);

#if HOTFIX_ENABLE
            //界面为lua写法的，具体可按照项目需要调整配置策略
            if(uiInfo.isLuauI.Trim() == "1")
            {
//                 LuaFunction createLuaUIFunc = XluaManager.Instance.createLuaUIFunc;
                 UILuaViewControllerBase luabase = new UILuaViewControllerBase();
//                 uiView = createLuaUIFunc.Func<string, UILuaViewBase, UILuaViewControllerBase>(uiInfo.classname, luabase);
                luabase.viewClassName = uiInfo.classname;
                uiView = luabase;
            }
            else
#endif
            {
                uiView = CreateClass<UIViewBase>("LazyFramework.UI." + uiInfo.classname);
            }
            //bundle弄好后改掉
            GameObject uiObjPrefab = Resources.Load<GameObject>(uiInfo.prefabname);
            GameObject uiObj = Instantiate(uiObjPrefab);
            uiObj.SetActive(true);
            uiObj.transform.SetParent(transform);
            uiObj.transform.localScale = Vector3.one;
            uiObj.transform.localPosition = Vector3.zero;
            uiObj.transform.localRotation = Quaternion.identity;
            uiView.Actor = uiObj;
            uiView.Initialize();
            return uiView;
        }
        private IEnumerator CreateUIAsync(UIType uiType,Action<UIViewBase> CallBack)
        {
            UIViewBase uiView = null;
            UIConfig.Info uiInfo = UIConfig.Instance.GetUIConfig(uiType);

#if HOTFIX_ENABLE
            //界面为lua写法的，具体可按照项目需要调整配置策略
            if (uiInfo.isLuauI.Trim() == "1")
            {
                //                 LuaFunction createLuaUIFunc = XluaManager.Instance.createLuaUIFunc;
                UILuaViewControllerBase luabase = new UILuaViewControllerBase();
                //                 uiView = createLuaUIFunc.Func<string, UILuaViewBase, UILuaViewControllerBase>(uiInfo.classname, luabase);
                luabase.viewClassName = uiInfo.classname;
                uiView = luabase;
            }
            else
#endif
            {
                uiView = CreateClass<UIViewBase>("LazyFramework.UI." + uiInfo.classname);
            }
            //bundle弄好后改掉
            ResourceRequest resourceRequest = Resources.LoadAsync<GameObject>(uiInfo.prefabname);
            yield return resourceRequest;
            GameObject prefab = resourceRequest.asset as GameObject;
            GameObject uiObj = Instantiate(prefab);
            prefab = null;
            uiObj.SetActive(true);
            uiObj.transform.SetParent(transform);
            uiObj.transform.localScale = Vector3.one;
            uiObj.transform.localPosition = Vector3.zero;
            uiObj.transform.localRotation = Quaternion.identity;
            uiView.Actor = uiObj;
            uiView.Initialize();
            CallBack(uiView);
        }
        public void Open(UIType uiType,System.Action<UIViewBase> callBack=null)
        {
            UIViewBase uiView = null;
            if (!m_allUIs.TryGetValue((int)uiType,out uiView))
            {
                uiView = CreateUI(uiType);
                m_allUIs[(int)uiType] = uiView;
            }
            uiView.Actor.SetActive(true);
            uiView.GetCanvas().renderMode = RenderMode.ScreenSpaceCamera;
            uiView.GetCanvas().worldCamera = m_UICamera;
            uiView.Open();
            if (callBack != null)
                callBack(uiView);
            if (!m_OpenUIs.Contains(uiView))
                m_OpenUIs.Add(uiView);
            UpdateSortOrder();
            uiView.SetLayer(m_UILayer);
        }
        public void OpenAsync(UIType uiType, System.Action<UIViewBase> callBack = null)
        {
            UIViewBase uiView = null;
            
            if (!m_allUIs.TryGetValue((int)uiType, out uiView))
            {
                if (!m_loadingUIs.ContainsKey((int)uiType))
                {
                    IEnumerator enumerator = CreateUIAsync(uiType, (viewBase) =>
                    {
                        uiView = viewBase;
                        m_allUIs[(int)uiType] = viewBase;

                        uiView.Actor.SetActive(true);
                        uiView.GetCanvas().renderMode = RenderMode.ScreenSpaceCamera;
                        uiView.GetCanvas().worldCamera = m_UICamera;
                        uiView.Open();
                        if (callBack != null)
                            callBack(uiView);
                        if (!m_OpenUIs.Contains(uiView))
                            m_OpenUIs.Add(uiView);
                        UpdateSortOrder();
                        uiView.SetLayer(m_UILayer);

                    });
                   Coroutine coroutine = StartCoroutine(enumerator);
                    if(coroutine!= null)        //协程没有yield return的时候 为null
                    {
                        m_loadingUIs[(int)uiType] = coroutine;
                    }
                }
            }
            else
            {
                uiView.Actor.SetActive(true);
                uiView.GetCanvas().renderMode = RenderMode.ScreenSpaceCamera;
                uiView.GetCanvas().worldCamera = m_UICamera;
                uiView.Open();
                if (callBack != null)
                    callBack(uiView);
                if (!m_OpenUIs.Contains(uiView))
                    m_OpenUIs.Add(uiView);
                UpdateSortOrder();
                uiView.SetLayer(m_UILayer);
            }
          
        }
        public void Close(UIType uiType,bool isReleas = false)
        {
            UIViewBase uiView = null;
            if (m_loadingUIs.ContainsKey((int)uiType))
            {
                if(m_loadingUIs[(int)uiType]!= null)
                {
                    StopCoroutine((Coroutine)m_loadingUIs[(int)uiType]);
                    m_loadingUIs[(int)uiType] = null;
                }
                m_loadingUIs.Remove((int)uiType);
            }
            if (!m_allUIs.TryGetValue((int)uiType, out uiView))
            {
                return;
            }
            if (m_OpenUIs.Contains(uiView))
                m_OpenUIs.Remove(uiView);
            if (!isReleas)
            {
                uiView.uiTTF = Time.realtimeSinceStartup;
                uiView.Actor.SetActive(false);
                uiView.Close();
            }
            else
            {
                uiView.Close();
                uiView.Release();
                DestroyImmediate(uiView.Actor);
                World.Active.DestroySystem(uiView);
                m_allUIs.Remove((int)uiType);

            }
        }

        private void UpdateSortOrder()
        {
            for(int i=0;i < m_OpenUIs.Count;++i)
            {
                UIViewBase uiView = m_OpenUIs[i];
                uiView.SetSortOrder((int)uiView.GetUILayer() + i + 10);
            }
        }

        //统一UI update
        private void Update()
        {
            TimerManager.Instance.AdvanceTime();
            if (m_ReleaseUI.Count > 0)
                m_ReleaseUI.Clear();
            var iter = m_allUIs.GetEnumerator();
            while (iter.MoveNext())
            {
                if (!iter.Current.Value.Actor.activeInHierarchy && Time.realtimeSinceStartup - iter.Current.Value.uiTTF > m_TTF)
                {
                    m_ReleaseUI.Add(iter.Current.Value);
                }
            }
            iter.Dispose();

            if(m_ReleaseUI.Count > 0)
            {
                for(int i=0;i < m_ReleaseUI.Count;++i)
                {
                    m_allUIs.Remove((int)m_ReleaseUI[i].GetUIType());
                    m_ReleaseUI[i].Release();
                    World.Active.DestroySystem(m_ReleaseUI[i]);
                    DestroyImmediate(m_ReleaseUI[i].Actor);
                }
            }
        }
        //统一UI FixedUpdate
        private void FixedUpdate()
        {
            var iter = m_allUIs.GetEnumerator();
            while (iter.MoveNext())
            {
                if (iter.Current.Value.Actor.activeInHierarchy)
                    iter.Current.Value.FixedUpdate();
            }
            iter.Dispose();
        }

        //统一UI LateUpdate
        private void LateUpdate()
        {
            var iter = m_allUIs.GetEnumerator();
            while (iter.MoveNext())
            {
                if (iter.Current.Value.Actor.activeInHierarchy)
                    iter.Current.Value.LateUpdate();
            }
            iter.Dispose();
        }
    }

}
